Build opus with NEON intrinsics on ARM (Android ABIs included) - #3833
Build opus with NEON intrinsics on ARM (Android ABIs included)#3833mcfnord wants to merge 2 commits into
Conversation
…tware#2806) The opus arch-optimisation block only matched the Android ABI names `armeabi-v7a` and `arm64-v8a`. Everywhere else Qt reports 64-bit ARM as `QT_ARCH=arm64` (Apple Silicon macOS, iOS, Linux aarch64), so those builds fell through to the plain-C opus path with no NEON acceleration. In fact the ARM NEON sources were never compiled on any target: the `SOURCES += $$SOURCES_OPUS_ARCH` line only lived in the x86 branch, so even the Android arch match populated the variable but never built it. Add an `arm64` branch that: - defines OPUS_ARM_MAY_HAVE_NEON_INTR (required for opus to include its arm/*.h headers) plus the PRESUME_NEON_INTR / PRESUME_AARCH64_NEON_INTR defines (NEON is part of the base AArch64 ISA, so it is always present); - compiles the NEON intrinsic sources, which need no special compiler flags, straight into SOURCES. Split SOURCES_OPUS_ARM into the self-contained NEON intrinsic files and the two NE10 files, which #include <NE10_dsp.h> from the external Ne10 library that Jamulus does not bundle; only the NEON subset is compiled. The x86 and Android arch matches are untouched: their generated Makefiles are byte-identical before and after this change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Should have Autobuild please build all targets |
| libs/opus/src/repacketizer.c | ||
|
|
||
| SOURCES_OPUS_ARM = libs/opus/celt/arm/armcpu.c \ | ||
| # NEON intrinsic sources: self-contained, need no external library. |
There was a problem hiding this comment.
| # NEON intrinsic sources: self-contained, need no external library. |
There was a problem hiding this comment.
🤖 AI: All three done in cbe7d44a. The comment line is gone. The NE10 pair is dropped: both files #include <NE10_dsp.h> unconditionally and Jamulus does not bundle Ne10, so no target has ever compiled them. The arm64 case is merged into the Android one, and the merge has a consequence: on main the Android ABIs define the PRESUME macros but compile zero libs/opus/*/arm/ files, because the SOURCES consumption branch covers only x86. Now all three ARM values of QT_ARCH compile the nine NEON files. Checked: the x86_64 Makefile is unchanged; a native Pi 4 build links the same nine _neon symbols as before; NDK r21d clang with Qt 5.15.2's flags compiles all 138 opus files for both Android ABIs, NEON being its default for armv7a-linux-androideabi. The Android CI job is green on this head.
CodeRabbit's summary took 142 lines to report that it had nothing actionable to say; a review with nothing to say has one right length.
|
Also this needs to be built, tested and analyzed on Apple Silicon. The arm handling in general is sketchy. For macOS Apple Silicon the explicit variable setting of arm64 is needed otherwise it tries to compile SSE for arm64 which obviously doesn't work |
|
Note 📡 STAND BY FOR AN LLM-AUTHORED MESSAGE. Native verification on a Raspberry Pi 4 (Cortex-A72, aarch64 Linux, not cross-compiled), including a result I didn't expect. Symbols: built this branch and the same base commit without it, both natively. CPU benefit: interleaved A/B benchmark (server pinned to one core, bot load, Why: confirmed with Bottom line: still worth merging — dead ARM code silently no-op'ing is a real defect on its own terms — but I'd frame it as a correctness/build-hygiene fix rather than a proven Jamulus performance win. This only covers Linux aarch64; it doesn't address the Apple Silicon question above. |
|
I'd love to get my local (Ubuntu 24.04 LTS) Android build working. Currently I rely on Github. |
|
Note 📡 STAND BY FOR AN LLM-AUTHORED MESSAGE. Catching up on the thread: @ann0see, re: build all targets — CI already did, on this PR's own run: Android APK, Linux arm64 @pljones, re: is #2806 mis-titled — fair catch, and a bit of both: #2806's title says "Mac ARM," which matches how the issue was originally reported, but this PR's actual scope is wider than that title suggests. It touches every non-Android 64-bit ARM target that reports My conclusion, for the record: native Pi 4 (Cortex-A72, Linux aarch64) testing confirms the fix is real and correct — all 9 NEON symbols ship where 0 did before — but produces no measurable CPU win for Jamulus specifically, at either complexity=1 (Jamulus's actual setting) or complexity=10 (max), because Jamulus's CELT-only Opus Custom mode only ever touches 2 of those 9 functions, combined under 1% of server CPU. That's a Jamulus-specific result, not a NEON-doesn't-help result — other opus consumers using SILK or the general encoder path would very plausibly see more. I'd still call this worth merging on correctness/build-hygiene grounds (dead ARM code silently no-op'ing across four platforms is a real defect on its own), just not on a proven performance claim. That's everything I can verify from here — Apple Silicon and a from-scratch Android build both remain open if anyone has the hardware. |
ann0see
left a comment
There was a problem hiding this comment.
Please clean up the comments as mentioned above.
Review follow-up on jamulussoftware#3833: - The arm64 case is merged into the existing Android case. All three ARM values of QT_ARCH (armeabi-v7a, arm64-v8a, arm64) now get the same headers, sources and defines, with OPUS_ARM_PRESUME_AARCH64_NEON_INTR added for the two 64-bit ones. OPUS_ARM_MAY_HAVE_NEON_INTR is defined for all of them: opus gates the inclusion of its arm/*.h headers on it, so without it the PRESUME defines select nothing. - The SOURCES consumption branch covers the Android ABIs too. On main it covers only x86, so the Android build defines the PRESUME macros but never compiles a single libs/opus/*/arm/ file (qmake-resolved on 2026-09-05: 0 arm sources for arm64-v8a and armeabi-v7a on main). - celt_fft_ne10.c and celt_mdct_ne10.c are removed from the list. They #include <NE10_dsp.h> unconditionally, Jamulus does not bundle Ne10, and no target has ever compiled them. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017veM89EdPrzUbWbb44aKQs
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: QUIET Plan: Advanced Run ID: 📒 Files selected for processing (1)
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review. 📝 WalkthroughWalkthroughThe ARM Opus build configuration now supports Android ARM ABIs and plain ChangesARM Opus build targeting
Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk: ⚪ Minimal · up to This change enables the intended Opus ARM NEON build path for supported ARM targets while excluding unsupported NE10 sources. The updated configuration has no identified merge-blocking risk. Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Out of Scope Changes checkExplanation The Android ABI source and define changes extend beyond issue [
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
🤖 AI: Fixes #2806.
Jamulus.pro's opus ARM block matched only the Android ABI names (armeabi-v7a,arm64-v8a), so every other 64-bit ARM build (Apple Silicon macOS, iOS, Linux aarch64, which Qt reports asQT_ARCH=arm64) compiled opus as plain C. The block was also inert where it did match:SOURCES += $$SOURCES_OPUS_ARCHexisted only in the x86 branch, andOPUS_ARM_MAY_HAVE_NEON_INTR, which gates opus'sarm/*.hheaders, was never defined. On main no target compiles a singlelibs/opus/*/arm/file.What this PR does
QT_ARCH: same headers, the 9 NEON intrinsic sources,OPUS_ARM_MAY_HAVE_NEON_INTR=1 OPUS_ARM_PRESUME_NEON=1 OPUS_ARM_PRESUME_NEON_INTR=1, plusOPUS_ARM_PRESUME_AARCH64_NEON_INTRfor the 64-bit ones.armv7a-linux-androideabi.celt_fft_ne10.candcelt_mdct_ne10.cremoved from the source list. They#include <NE10_dsp.h>unconditionally, Jamulus does not bundle Ne10, and no target has ever compiled them.The Android ABIs therefore compile the NEON sources for the first time; x86 builds are untouched.
Testing
qmake-resolvedMakefile.ReleaseperQT_ARCH: x86_64 identical before and after;arm64,arm64-v8a,armeabi-v7aeach list the 9 ARM sources and the defines above; main lists 0 ARM sources for the Android ABIs.CONFIG+=headless): links, 9_neonsymbols in the binary, 0 undefined.android-clangflags (-target <abi>30 -Oz -fPIC): all 138 opus sources compile forarmv7a-linux-androideabi30andaarch64-linux-android30, 0 failures, and every_neonsymbol the objects reference is defined in the set.🤖 This message was written by AI and reviewed by @mcfnord.